#include "catalog.h"
#include "query.h"
#include "sort.h"
#include "index.h"

#define MAX(a,b) ((a) > (b) ? (a) : (b))

/*
 * Joins two relations.
 *
 * Returns:
 * 	OK on success
 * 	an error code otherwise
 */
Status Operators::Join(const string & result,      // name of the output relation 
                       const int projCnt,          // number of attributes in the projection
	               const attrInfo projNames[], // the list of projection attributes
	               const attrInfo *attr1,      // left attr in the join predicate
	               const Operator op,          // the predicate operation 
	               const attrInfo *attr2)     // right attr in the join predicate
{
	//First thing to do is convert attrInfo's to attrDesc
	AttrDesc descProjNames[projCnt];
	AttrDesc descProj;
	for(int x = 0; x < projCnt; x++)
	{
		Status descproj_status = attrCat->getInfo(projNames[x].relName, projNames[x].attrName, descProj);

		if(descproj_status != OK)
			return descproj_status;

		descProjNames[x] = descProj;
	}
	AttrDesc Attr1Desc, Attr2Desc;
	Status lStatus = attrCat->getInfo(attr1->relName, attr1->attrName, Attr1Desc);
	if(lStatus != OK)
		return lStatus;
	lStatus = attrCat->getInfo(attr2->relName, attr2->attrName, Attr2Desc);
	if(lStatus != OK)
		return lStatus;

	//Now get the reclen

	AttrDesc *resultDesc;
	int resultCnt;
	int rec_length = 0;
	Status result_info_status = attrCat->getRelInfo(result, resultCnt, resultDesc);
	if(result_info_status != OK)
		return result_info_status;

	for(int j = 0; j < resultCnt; j++)
	{
		rec_length += resultDesc[j].attrLen;
	}

	if(op != EQ)
	{
		//MUST ust SNL

		SNL(result, projCnt, descProjNames, Attr1Desc, op, Attr2Desc, rec_length);
	}
	else
	{
		//check for an index on either attr1 or attr2
		if(Attr1Desc.indexed || Attr2Desc.indexed)
		{
			if(Attr2Desc.indexed)
			{
		        	INL(result, projCnt, descProjNames, Attr1Desc, op, Attr2Desc, rec_length);
			}
			else
			{
				INL(result, projCnt, descProjNames, Attr2Desc, op, Attr1Desc, rec_length);
			}
		}
		else
		{
			SMJ(result, projCnt, descProjNames, Attr1Desc, op, Attr2Desc, rec_length);
		}
	}



	return OK;
}
